POLIMORFISMO

MENTAL, un lenguaje polimórfico sin sobrecarga

“Polimorfismo es la cualidad de lo que tiene o puede tener distintas formas” (Diccionario de la R.A.E.)

“Polimorfismo es la cualidad o estado de existir en o asumir diferentes formas” (Diccionario Merriam-Webster)



Concepto

Polimorfismo significa “muchas formas”. Es lo contrario de monomorfismo y se refiere, en general, a la aparición de elementos de distinto tipo en alguna expresión del lenguaje.

Si una expresión tiene significados diferentes en función de los tipos de sus componentes, se dice que la expresión polimórfica está “sobrecargada” (de semántica, se sobreentiende). Si la semántica se mantiene en todo momento, el polimorfismo es sin sobrecarga.


Tipos de expresiones polimórficas
Polimorfismo implícito y explícito

Se aplican a cabeceras de procedimientos. Cuando se definen parámetros de tipo (y, por lo tanto, en los argumentos de la llamada), se habla de polimorfismo explícito.

En el polimorfismo implícito no existe parámetro de tipo, siendo el procesador del lenguaje el encargado de “descubrir” los tipos de los argumentos.


Resolución

El polimorfismo con sobrecarga requiere un proceso adicional llamado “resolución”, que consiste en determinar la semántica a aplicar entre las diferentes posibles. Esta resolución puede tener lugar en tiempo de compilación (polimorfismo estático) o en tiempo de ejecución (polimorfismo dinámico).

La resolución puede ser un proceso relativamente simple (por ejemplo en los operadores aritméticos observando los argumentos) o más complejo. La resolución es más difícil si no existen o son opcionales las declaraciones de los identificadores.

En la resolución de la sobrecarga, Tennenbaum [1974] distingue entre:
  1. Resolución hacia adelante. Determina el conjunto de tipos posibles de un operador a partir de sus operandos.

  2. Resolución hacia atrás. Basada en el tipo previsto según el contexto.
Por ejemplo, en Ada, la resolución de la sobrecarga se realiza mediante una pasada hacia adelante y otra hacia atrás.


¿Qué tipo de polimorfismo interesa más?

El polimorfismo con sobrecarga tiene dos inconvenientes:
  1. Crea confusión, pues hay diferentes semánticas en juego.
  2. Hay que realizar un proceso de resolución, lo que consume recursos.
En cambio, el polimorfismo sin sobrecarga mantiene la semántica en todo momento y también la consistencia. Por lo tanto, sólo nos interesa el polimorfismo sin sobrecarga.


Ventajas del polimorfismo sin sobrecarga
  1. Facilita la especificación de algoritmos, orientándolos a su aspecto conceptual o semántico, liberando la codificación de aspectos de bajo nivel.

  2. Generaliza la codificación. Un mismo algoritmo puede servir para acceder a manipular diferentes estructuras de datos, independientemente de los tipo de los elementos constituyentes. Por ejemplo, una función que devuelve la longitud de una lista, que accede a un elemento de una lista, etc. independientemente del tipo de sus elementos.

  3. Simplifica la programación. No es necesario codificar diferentes procedimientos para cada tipo de elemento.

  4. Supone una relajación de las estrictas normas o reglas operativas y proporciona, por lo tanto, un mayor grado de libertad y flexibilidad.

  5. Las operaciones polimórficas ponen de manifiesto una esencia común, una abstracción en definitiva que es independiente de los elementos sobre los que opera.

  6. Proporciona un sistema combinatorio indispensable para relacionar elementos de diferente tipo, favoreciendo la creatividad.

MENTAL y el Polimorfismo

Primitivas semánticas sin sobrecarga

MENTAL es un lenguaje polimórfico sin sobrecarga. Por ejemplo, en la expresión x+y, x e y pueden ser cualquier tipo de expresión, pero la semántica se mantiene. Es decir, si x e y son dos matrices y son iguales, el resultado es 2*x. Y si sumamos dos expresiones iguales a x+y, el resultado es 2*⟨x+y.

Todas las primitivas semánticas son polimórficas sin sobrecarga, es decir, la semántica asociada a cada primitiva es siempre la misma. Es decir, la suma siempre es suma, la sustitución es siempre sustitución, etc. Tiene que ser así forzosamente, pues la universalidad de las primitivas así lo exige. Y además el polimorfismo está íntimamente relacionado con la libertad, con la posibilidad de formar expresiones sin restricciones. Cuando una expresión polimórfica no tiene posibilidad de evaluarse, se autoevalúa.


Ejemplos de expresiones polimórficas con las primitivas semánticas
  1. ( a/b 17.5 ⟨( f(x y) = x+y+7 )⟩ ) // secuencia

  2. { a/b f(3 4) ⟨( f(x y) = x+y+7 )⟩ } // conjunto

  3. ( ⟨( f(x y) = x+y+7 )⟩ + 12 ) // suma

  4. (x+y+z = {a b c}) // sustitución

  5. ( ⟨( f(x y) = x+y+7 )⟩ = 33 ) // sustitución

  6. color/⟨( f(x y) = x+y+7 )⟩ // particularización

  7. (a/b ≡ 33) // equivalencia

  8. (33 ← a/b) // condición

  9. (a/b 17.5 "texto")↓ // acceso al contenido de una secuencia

Operaciones derivadas y polimorfismo

Las operaciones derivadas pueden ser totalmente polimórficas o parcialmente polimórficas, dependiendo de sus definiciones. Cuando las variables son de un determinado tipo, eso indica que se exige forzosamente ese tipo para que tenga sentido. Si el tipo no se ajusta al previsto, la expresión se autoevalúa. Ejemplos:
Números enteros y polimorfismo

Un número entero, por ejemplo 1234, es una secuencia de dígitos, pues representa, de forma compacta, a la secuencia (1 2 3 4). SEgún la operación, se trata como número o como secuencia. Ejemplos:

1234*5 // ev. 6170 (1234 se trata como número entero)

(1234 ∪ ab) // ev. 1234ab (1234 se trata como secuencia)



Condición como existencia

Una expresión que hace de condición se interpreta como existencia. Ejemplo:

La expresión (x ← a=b) se interpreta como x si existe (se cumple) la igualdad a=b.


Operadores con atributos

Con el fin de simplificar el número de operadores, se puede utilizar un mismo operador con diferentes atributos para así facilitar la conexión conceptual con el operador. Por ejemplo, Ejemplos:
  1. Suma vectorial:

    ⟨( x +/v y) =: ( [x\⌊1…x#⌋ + y\⌊1…y#⌋] ) )⟩

    (a = (11 22 33))
    (b = (1 2 3))
    (a +/v b) // ev. (11+1 + 22+2 + 33+3) ev. (12 24 36)


  2. Producto escalar de dos vectores:

    ⟨( x */e y) =: +⊣( [x\⌊1…x#⌋ * y\⌊1…y#⌋] ) )⟩

    (a = (11 22 33))
    (b = (1 2 3)
    (a */e b) // ev. (11*1 + 22*2 + 33*3) ev. 154


Bibliografía